﻿#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<string>
using namespace std;


//多态条件：
//1.虚函数重写（三同）
//2.父类的指针或引用去调用虚函数


#if 0
//认识多态，协变（基类和派生类的函数返回值类型可以不同但是必须是父子类关系的指针或引用）
class A {};
class B :public A{};

class Person 
{
public:
	virtual A* BuyTicket() { cout << "买票-全价" << endl; return nullptr; }//
};
class Student : public Person 
{
public:
	virtual B* BuyTicket() { cout << "买票-半价" << endl; return nullptr; }//
};
void Func(Person& p)
{
	p.BuyTicket();
}
int main()
{
	Person ps;
	Student st;
	Func(ps);
	Func(st);
	return 0;
}

//析构函数的重写
class Person {
public:
	virtual ~Person() 
	{
		cout << "~Person()" << endl; 
	}
};
class Student : public Person {
public:
	virtual ~Student() 
	{ 
		cout << "~Student()" << endl; 
	}
};
int main()
{
	Person* p1 = new Person;
	Person* p2 = new Student;
	delete p1;
	delete p2;

	return 0;
}

//重写和重定义
class A 
{ 
	public: virtual void test(float a) { cout << a; } //没有构成多态，而是隐藏
}; 
class B :public A 
{ 
	public: virtual void test(int b) { cout << b; } 
}; 
void main() 
{
	A* a = new A; B* b = new B; a = b; a->test(1.1); 
}

//重写和重定义（隐藏）
class A
{
public:

  void f1() { cout << "A::f1()" << endl; }//重定义

  virtual void f2() { cout << "A::f2()" << endl; }//重写

  virtual void f3() { cout << "A::f3()" << endl; }//重写

};
class B : public A
{

public:

	virtual void f1() { cout << "B::f1()" << endl; }

	virtual void f2() { cout << "B::f2()" << endl; }

	void f3() { cout << "B::f3()" << endl; }

};
int main()
{
	A a;
	B b;
	A& aa = b;
	aa.f2();
	aa.f1();
	aa.f3();
}

//抽象类
class Car//抽象类（不能实例化对象）
{
public:
	virtual void Drive() = 0;//纯虚函数
};
class Benz :public Car//继承后也不能实例化对象(除非重写)
{
public:
	virtual void Drive()
	{
		cout << "Benz-舒适" << endl;
	}
};
class BMW :public Car//继承后也不能实例化对象(除非重写)
{
public:
	virtual void Drive()
	{
		cout << "BMW-操控" << endl;
	}
};
int main()
{
	Car* pBenz = new Benz;
	pBenz->Drive();
	Car* pBMW = new BMW;
	pBMW->Drive();
}

//经典例题
//子类在虚函数重写时重写的是函数内部的实现，而函数声明接口的部分是从父类继承下来的
class A
{
public:
	virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }
	virtual void test() { func(); }
};
class B : public A
{
public:
	void func(int val = 0) { std::cout << "B->" << val << std::endl; }
};
int main(int argc, char* argv[])
{
	B* p = new B;
	p->test();
	return 0;
}


//  所有虚函数都是存在虚表内吗？
class Base {
public:
	virtual void func1() { cout << "Base::func1" << endl; }
	virtual void func2() { cout << "Base::func2" << endl; }
private:
	int a;
};
class Derive :public Base {
public:
	virtual void func1() { cout << "Derive::func1" << endl; }
	virtual void func3() { cout << "Derive::func3" << endl; }
	virtual void func4() { cout << "Derive::func4" << endl; }
private:
	int b;
};
typedef void(*VF)();//将无参的函数指针类型重命名成VF
void Print(VF* p)//该函数是为了实现打印虚函数的指针并且直接调用函数指针
{
	int i = 1;
	while (*p)
	{
		printf("func%d = %p->",i++, *p);
		(*p)();//*p就是虚表里的函数指针，可以代替函数名直接调用函数
		p++;
	}

}
int main()
{
	Base b;
	Derive d;
	Print((VF*)*(long long*)&b);//传虚表的地址
	cout << endl;
	Print((VF*)*(long long*)&d);
	//*(long long*)&b 是拿到对象中前八个字节的内容，也就是虚表指针
	//防止传参时类型不匹配，强转

 	return 0;
}



//多继承下的虚表存放
class Base1 {
public:
	virtual void func1() { cout << "Base1::func1" << endl; }
	virtual void func2() { cout << "Base1::func2" << endl; }
private:
	int b1;
};
class Base2 {
public:
	virtual void func1() { cout << "Base2::func1" << endl; }
	virtual void func2() { cout << "Base2::func2" << endl; }
private:
	int b2;
};
class Derive : public Base2, public Base1 {
public:

	virtual void func1() { cout << "Derive::func1" << endl; }
	virtual void func3() { cout << "Derive::func3" << endl; }
private:
	int d1;
};

typedef void(*VF)();//将无参的函数指针类型重命名成VF
void Print(VF* p)//该函数是为了实现打印虚表内的函数指针并且直接调用
{
	int i = 1;
	while (*p)
	{
		printf("func%d = %p->", i++, *p);
		(*p)();//*p就是虚表里的函数指针，可以代替函数名直接调用函数
		p++;
	}

}
int main()
{
	Derive d;
	//打印第一张虚表
	Print((VF*)*(long long*)&d);
	cout << endl;
	//打印第二张虚表
	Base1* b = &d;//切片处理 
	Print((VF*)*(long long*)b);
	

	return 0;
}

#endif

class A
{
public:
	virtual void func1()
	{
		cout << "A::void func1()" << endl;
	}
	int _a;
};
class B:virtual public A
{
public:
	virtual void func1()
	{
		cout << "B::void func1()" << endl;
	}
	int _b;
};
class C :virtual public A
{
public:
	virtual void func1()
	{
		cout << "C::void func1()" << endl;
	}
	int _c;
};
class D:public B ,public C
{
public:
	virtual void func1()
	{
		cout << "D::void func1()" << endl;
	}
	int _d;
};

int main()
{
	A a;
	B b;
	C c;
	D d;
	
	return 0;
}